function varargout = TLAutoscalingDlg(varargin)

% TL_AUTOSCALING_DLG is the dialog function of Worst Case Autoscaling Tool
%
% INPUT ARGUMENTS
%    action      first input item, which describes the selected action
%    handle      second necessary input: current model handle
%
% OUTPUT ARGUMENTS
%    struct of calculated results
%
% EXAMPLES
%   TLAutoscalingDlg('Create', handle)
%      - create dialog window of worst-case autoscaling tool


% Author(s): D. Andoleit, J. Fransing
% $RCSfile: TLAutoscalingDlg.m $
% $ProjectName: e:/ARC/Components/HostSW/ProdCodeGen/AutoScaler/Sources/MSrc/project.pj $
% $Revision: 1.20 $
% $Date: 2011/08/30 08:21:27MESZ $
%
% Copyright (c) 2008 dSPACE GmbH. All rights reserved.


% default return value
varargout{1} = [];

% default input value
if isempty(varargin)
    varargin{1} = 'Create';
    currModelName = ds_get_current_model;
    if ~isempty(currModelName)
        varargin{2} = get_param(currModelName, 'Handle');
    else
        ds_error_msg( ...
            'No model open or current Simulink system is not in a valid model.', ...
            'Title'          ,'Autoscaling Tool Message', ...
            'ShowDialog'     ,'on', ...
            'MessageType'    ,'fatal', ...
            'RegisterMessage','on', ...
            'MessageNumber'  , 0);
        return;
    end
end

% get action string
action = varargin{1};
if ~ischar(action)
    ds_error_msg( ...
        'Invalid action string.', ...
        'Title'        ,'Autoscaling Tool Message', ...
        'ShowDialog'   ,'off', ...
        'MessageType'  ,'error', ...
        'MessageNumber', 0);
    return;
end

% perform selected action
switch(lower(action))
    case 'create'
        % create the dialog window
        ds_error_none;
        if nargin < 3
            FcnCreate(varargin{2},[]);
        else
            FcnCreate(varargin{2},varargin{3});
        end
        if ds_error_check, return; end

        %%% range page %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    case 'selectcurrent'
        % synchronize data after user input
        varargout{1} = FcnSelectCurrent(varargin{2});
        if ds_error_check, return; end
    case 'refreshnetlist'
        % synchronize data after user input
        varargout{1} = FcnRefreshNetlist(varargin{2});
        if ds_error_check, return; end
    case 'propagateknownranges'
        % synchronize data after user input
        varargout{1} = FcnPropagateKnownRanges(varargin{2});
        if ds_error_check, return; end
    case 'calculateworstcaseranges'
        % synchronize data after user input
        varargout{1} = FcnCalculateWorstCaseRanges(varargin{2});
        if ds_error_check, return; end
    case 'setrangescolor'
        % synchronize data after user input
        varargout{1} = FcnSetColor(varargin{2});
        if ds_error_check, return; end
    case 'resetranges'
        % synchronize data after user input
        varargout{1} = FcnResetRanges(varargin{2});
        if ds_error_check, return; end
    case 'resetrangescolor'
        % synchronize data after user input
        varargout{1} = FcnResetColor(varargin{2});
        if ds_error_check, return; end
    case 'saverangestofile'
        % synchronize data after user input
        varargout{1} = FcnSaveRangesToFile(varargin{2});
        if ds_error_check, return; end
    case 'showranges'
        % synchronize data after user input
        varargout{1} = FcnShowRanges(varargin{2});
        if ds_error_check, return; end
    case 'loadrangesfromfile'
        % synchronize data after user input
        varargout{1} = FcnLoadRangesFromFile(varargin{2});
        if ds_error_check, return; end
    case 'hideranges'
        % synchronize data after user input
        varargout{1} = FcnHideRanges(varargin{2});
        if ds_error_check, return; end

        %%scaling page %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    case 'inheritscaling'
        % synchronize data after user input
        varargout{1} = FcnInheritScaling(varargin{2});
        if ds_error_check, return; end
    case 'startautoscaling'
        % synchronize data after user input
        varargout{1} = FcnStartAutoscaling(varargin{2});
        if ds_error_check, return; end
    case 'setscalingcolor'
        % synchronize data after user input
        varargout{1} = FcnSetColor(varargin{2});
        if ds_error_check, return; end
    case 'resetscalingcolor'
        % synchronize data after user input
        varargout{1} = FcnResetColor(varargin{2});
        if ds_error_check, return; end
    case 'showscaling'
        % synchronize data after user input
        varargout{1} = FcnShowScaling(varargin{2});
        if ds_error_check, return; end
    case 'resetscaling'
        % synchronize data after user input
        varargout{1} = FcnResetScaling(varargin{2});
        if ds_error_check, return; end
    case 'hidescaling'
        % synchronize data after user input
        varargout{1} = FcnHideScaling(varargin{2});
        if ds_error_check, return; end

        %%% standard callbacks %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    case 'sync'
        % synchronize data after user input
        varargout{1} = FcnSync(varargin{2});
        if ds_error_check, return; end
    case 'apply'
        % callback for Apply button
        varargout{1} = FcnApply(varargin{2});
        if ds_error_check, return; end
    case 'revert'
        % callback for Apply button
        varargout{1} = FcnRevert(varargin{2});
        if ds_error_check, return; end
    case 'help'
        ds_error_none;
        varargout{1} = FcnHelp(varargin{2});
        if ds_error_check, return; end
    case 'cancel'
        % callback for Cancel button
        varargout{1} = FcnCancel(varargin{2});
        if ds_error_check, return; end
    case 'close'
        % callback for Ok button
        varargout{1} = FcnClose(varargin{2});
        if ds_error_check, return; end
    case 'codeedit'
        % return the block data description
        varargout{1} = FcnCodeEditor(varargin{2});
        if ds_error_check, return; end
    case 'getdatadescription'
        % return the block data description
        varargout{1} = FcnGetDataDescription;
        if ds_error_check, return; end
    otherwise
        ds_error_msg( ...
            'Invalid action string.', ...
            'Title'        ,'Autoscaling Tool Message', ...
            'ShowDialog'   ,'off', ...
            'MessageType'  ,'fatal', ...
            'MessageNumber', 0);
end

%================================================================================
%% subsystem selection
%================================================================================
function userData = FcnSelectCurrent(userData)

set(userData.hDlg,'pointer','watch');

% clear pending error messages
ds_error_none;

% selected no TL block
switch get_param(gcb,'blocktype')
    case 'SubSystem'
        % the block is a subsystem
        if strcmp(get_param(gcbh,'Selected'),'on') && ~ds_isa(gcb, 'tlblock')
            % gcb is selected -> take the block
            selected = gcb;
        else
            % gcb is not selected -> take the current subsystem
            selected = gcs;
        end
    case 'ModelReference'
        % take the referenced model
        objMR = get_param(gcb, 'Object');
        selected = objMR.ModelName;
        if ~any(strcmp(find_system('type','block_diagram'),selected))
            open_system(selected);
        end
    otherwise
        % take the current subsystem
        selected = gcs;
end

if ~tl_is_valid_incr_system(bdroot(selected))
    msgData = ds_error_get('CurrentState');
    [dummyPath,tlPath] = get_tlsubsystempath(selected);
    % tlPath is empty, if TL subsystem or block outside TL system is selected
    % dummyPath contains path between selected block and TL system
    if ~isempty(tlPath)
        tlSubInfo = tl_get_subsystem_info(tlPath);
    else
        tlSubInfo = tl_get_subsystem_info(dummyPath);
    end
    ds_error_merge(msgData);

    if ~isempty(tlSubInfo.tlSubsystemPath) && ~isempty(tlSubInfo.milSubsystemPath)
        if length(selected) < length(tlSubInfo.milSubsystemPath)
            selected = tlSubInfo.milSubsystemPath;
        end
    else
        selected = [];
    end
end
if ~isempty(selected)
    % insert the selected subsystem into the edit box
    userData.uiControl(17).value = selected;
    crIdx = strfind(userData.uiControl(17).value,char(10));
    subsystemString = userData.uiControl(17).value;
    subsystemString(crIdx) = char(32);
    userData.uiControl(2).value = subsystemString;
else
    ds_error_msg( ...
        'No valid TargetLink system selected.', ...
        'Title'          ,'Autoscaling Tool Message', ...
        'ShowDialog'     ,'on', ...
        'RegisterMessage', 'off', ...
        'MessageType'    ,'note', ...
        'MessageNumber'  , 03464);
end

% show the errors, warnings and notes
FcnShowMsg(userData);

userData.bApplyUiControls = 1;
userData.bApplyData       = 0;
userData.bClose           = 0;


%================================================================================
%% init
%================================================================================
function userData = FcnRefreshNetlist(userData)

set(userData.statusLine.handle,'string','Refresh netlist ... ');
[options,backupASDS] = FcnPrepare(userData);
[exept,userData] = FcnCatchError(userData,backupASDS);
if exept
    return;
end

% call API command
if isfield(userData,'asds')
    userData.asds = tl_autoscaling('init', ...
        'useexistingasds',userData.asds, ...
        'useoptionsstruct',options);
else
    userData.asds = tl_autoscaling('init','useoptionsstruct',options);
end
[exept,userData] = FcnCatchError(userData,backupASDS);
if exept
    return;
end

% update status line
userData = FcnUpdateStatusLine(userData,1);
% show the errors, warnings and notes
FcnShowMsg(userData);

userData.bApplyUiControls = 1;
userData.bApplyData       = 0;
userData.bClose           = 0;

%================================================================================
%% propagateranges
%================================================================================
function userData = FcnPropagateKnownRanges(userData)

set(userData.statusLine.handle,'string','Propagate ranges ... ');
[options,backupASDS] = FcnPrepare(userData);
[exept,userData] = FcnCatchError(userData,backupASDS);
if exept
    return;
end

% call API command
if isfield(userData,'asds')
    userData.asds = tl_autoscaling('propagateranges', ...
        'useexistingasds',userData.asds, ...
        'useoptionsstruct',options);
else
    userData.asds = tl_autoscaling('propagateranges','useoptionsstruct',options);
end
[exept,userData] = FcnCatchError(userData,backupASDS);
if exept
    return;
end

% update status line
userData = FcnUpdateStatusLine(userData,1);
% show the errors, warnings and notes
FcnShowMsg(userData);

userData.bApplyUiControls = 1;
userData.bApplyData       = 0;
userData.bClose           = 0;

%================================================================================
%% calculateranges
%================================================================================
function userData = FcnCalculateWorstCaseRanges(userData)

set(userData.statusLine.handle,'string','Calculate ranges ... ');
[options,backupASDS] = FcnPrepare(userData);
[exept,userData] = FcnCatchError(userData,backupASDS);
if exept
    return;
end

% call API command
if isfield(userData,'asds')
    userData.asds = tl_autoscaling('calculateranges', ...
        'useexistingasds',userData.asds, ...
        'useoptionsstruct',options);
else
    userData.asds = tl_autoscaling('calculateranges','useoptionsstruct',options);
end
[exept,userData] = FcnCatchError(userData,backupASDS);
if exept
    return;
end

% update status line
userData = FcnUpdateStatusLine(userData,1);
% show the errors, warnings and notes
FcnShowMsg(userData);

userData.bApplyUiControls = 1;
userData.bApplyData       = 0;
userData.bClose           = 0;


%================================================================================
%% resetranges
%================================================================================
function userData = FcnResetRanges(userData)

set(userData.statusLine.handle,'string','Propagate ranges ... ');
[options,backupASDS] = FcnPrepare(userData);
[exept,userData] = FcnCatchError(userData,backupASDS);
if exept
    return;
end

% call API command
if isfield(userData,'asds')
    userData.asds = tl_autoscaling('resetranges', ...
        'useexistingasds',userData.asds, ...
        'useoptionsstruct',options);
else
    userData.asds = tl_autoscaling('resetranges', ...
        'useoptionsstruct',options);
end
[exept,userData] = FcnCatchError(userData,backupASDS);
if exept
    return;
end

% update status line
userData = FcnUpdateStatusLine(userData,1);
% show the errors, warnings and notes
FcnShowMsg(userData);

userData.bApplyUiControls = 1;
userData.bApplyData       = 0;
userData.bClose           = 0;

%================================================================================
%% saveranges
%================================================================================
function userData = FcnSaveRangesToFile(userData)

set(userData.statusLine.handle,'string','Save ranges ... ');
[options,backupASDS] = FcnPrepare(userData);
[exept,userData] = FcnCatchError(userData,backupASDS);
if exept
    return;
end

if isfield(userData,'asds')
    % get filename with file selection dialog
    [file,path] = uiputfile('*.mat','Save Ranges in');
    if ischar(file) && ischar(path)
        strIdx = findstr(file, '.mat');
        if isempty(strIdx) ||  lt(strIdx(end), length(file) - 3)
            filename = [path file '.mat'];
            fileexist = dir(filename);
            if ~isempty(fileexist)
                % ask to replace the existing file
                dlgbutton = questdlg( ...
                    ['' filename ''' already exists.', char(10), ...
                    'Do you want to replace it?'], ...
                    'Save Ranges in','Yes','No','No');
                if strcmp(dlgbutton,'Yes')
                    % replace the file
                    userData.asds = tl_autoscaling('saveranges', ...
                        'useexistingasds',userData.asds, ...
                        'useoptionsstruct',options, ...
                        'filename',filename);
                end
            else
                % save in file
                userData.asds = tl_autoscaling('saveranges', ...
                    'useexistingasds',userData.asds, ...
                    'useoptionsstruct',options, ...
                    'filename',filename);
            end
        else
            filename = [path file];
            %save the file
            userData.asds = tl_autoscaling('saveranges', ...
                'useexistingasds',userData.asds, ...
                'useoptionsstruct',options, ...
                'filename',filename);
        end
    end
end
[exept,userData] = FcnCatchError(userData,backupASDS);
if exept
    return;
end

% update status line
userData = FcnUpdateStatusLine(userData,1);
% show the errors, warnings and notes
FcnShowMsg(userData);

userData.bApplyUiControls = 1;
userData.bApplyData       = 0;
userData.bClose           = 0;

%================================================================================
%% loadranges
%================================================================================
function userData = FcnLoadRangesFromFile(userData)

set(userData.statusLine.handle,'string','Load ranges ... ');
[options,backupASDS] = FcnPrepare(userData);
[exept,userData] = FcnCatchError(userData,backupASDS);
if exept
    return;
end

if isfield(userData,'asds')
    [file,path] = uigetfile('*.mat','Select the file with the saved ranges ');
    if ischar(file) && ischar(path)
        filename = [path file];
        userData.asds = tl_autoscaling('loadranges', ...
            'useexistingasds',userData.asds, ...
            'useoptionsstruct',options, ...
            'filename',filename);
    end
end
[exept,userData] = FcnCatchError(userData,backupASDS);
if exept
    return;
end

% update status line
userData = FcnUpdateStatusLine(userData,0);
% show the errors, warnings and notes
FcnShowMsg(userData);

userData.bApplyUiControls = 1;
userData.bApplyData       = 0;
userData.bClose           = 0;

%================================================================================
%% setcolor
%================================================================================
function userData = FcnSetColor(userData)

set(userData.statusLine.handle,'string','Set color ... ');
[options,backupASDS] = FcnPrepare(userData);
[exept,userData] = FcnCatchError(userData,backupASDS);
if exept
    return;
end

if isfield(userData,'asds')
    userData.asds = tl_autoscaling('setcolor', ...
        'useexistingasds',userData.asds, ...
        'useoptionsstruct',options);
else
    % reset hiliting for blocks which are in scope
    scope = tl_get_blocks(options.subsystemh,'TLScalable')';
    for handle = scope
        set_param(handle,'HiliteAncestors','none');
    end
end
[exept,userData] = FcnCatchError(userData,backupASDS);
if exept
    return;
end

% update status line
userData = FcnUpdateStatusLine(userData,0);
% show the errors, warnings and notes
FcnShowMsg(userData);

userData.bApplyUiControls = 1;
userData.bApplyData       = 0;
userData.bClose           = 0;

%================================================================================
%% resetcolor
%================================================================================
function userData = FcnResetColor(userData)

set(userData.statusLine.handle,'string','Reset color ... ');
[options,backupASDS] = FcnPrepare(userData);
[exept,userData] = FcnCatchError(userData,backupASDS);
if exept
    return;
end

if isfield(userData,'asds')
    userData.asds = tl_autoscaling('resetcolor', ...
        'useexistingasds',userData.asds, ...
        'useoptionsstruct',options);
else
    % reset hiliting for blocks which are in scope
    scope = tl_get_blocks(options.subsystemh,'TLScalable')';
    for handle = scope
        set_param(handle,'HiliteAncestors','none');
    end
end
[exept,userData] = FcnCatchError(userData,backupASDS);
if exept
    return;
end

% update status line
userData = FcnUpdateStatusLine(userData,0);
% show the errors, warnings and notes
FcnShowMsg(userData);

userData.bApplyUiControls = 1;
userData.bApplyData       = 0;
userData.bClose           = 0;

%================================================================================
%% showranges
%================================================================================
function userData = FcnShowRanges(userData)

set(userData.statusLine.handle,'string','Show ranges ... ');
[options,backupASDS] = FcnPrepare(userData);
[exept,userData] = FcnCatchError(userData,backupASDS);
if exept
    return;
end

if isfield(userData,'asds')
    % use the existing netlist
    userData.asds = tl_autoscaling('showranges', ...
        'useexistingasds',userData.asds, ...
        'useoptionsstruct',options);
else
    % create a netlist
    userData.asds = tl_autoscaling('showranges', ...
        'useoptionsstruct',options);
end
[exept,userData] = FcnCatchError(userData,backupASDS);
if exept
    return;
end

% update status line
userData = FcnUpdateStatusLine(userData,0);
% show the errors, warnings and notes
FcnShowMsg(userData);

userData.bApplyUiControls = 1;
userData.bApplyData       = 0;
userData.bClose           = 0;


%================================================================================
%% hideranges
%================================================================================
function userData = FcnHideRanges(userData)

set(userData.statusLine.handle,'string','Hide ranges ... ');
[options,backupASDS] = FcnPrepare(userData);
[exept,userData] = FcnCatchError(userData,backupASDS);
if exept
    return;
end

if isfield(userData,'asds')
    userData.asds = tl_autoscaling('hideranges', ...
        'useexistingasds',userData.asds, ...
        'useoptionsstruct',options);
end
[exept,userData] = FcnCatchError(userData,backupASDS);
if exept
    return;
end

% update status line
userData = FcnUpdateStatusLine(userData,0);
% show the errors, warnings and notes
FcnShowMsg(userData);

userData.bApplyUiControls = 1;
userData.bApplyData       = 0;
userData.bClose           = 0;

%================================================================================
%% inheritscaling
%================================================================================
function userData = FcnInheritScaling(userData)

set(userData.statusLine.handle,'string','Inherit scaling ...');
[options,backupASDS] = FcnPrepare(userData);
[exept,userData] = FcnCatchError(userData,backupASDS);
if exept
    return;
end

if isfield(userData,'asds')
    % use existing netlist
    userData.asds = tl_autoscaling('inheritscaling', ...
        'useexistingasds',userData.asds, ...
        'useoptionsstruct',options);
else
    % create a netlist
    userData.asds = tl_autoscaling('inheritscaling', ...
        'useoptionsstruct',options);
end
[exept,userData] = FcnCatchError(userData,backupASDS);
if exept
    return;
end

% update status line
userData = FcnUpdateStatusLine(userData,0);
% show the errors, warnings and notes
FcnShowMsg(userData);

userData.bApplyUiControls = 1;
userData.bApplyData       = 0;
userData.bClose           = 0;

%================================================================================
%% calculatescaling
%================================================================================
function userData = FcnStartAutoscaling(userData)

bClearUserData = 0;
[options,backupASDS] = FcnPrepare(userData);
[exept,userData] = FcnCatchError(userData,backupASDS);
if exept
    return;
end
if ~options.scaleOutputs && ~options.scaleStates && ~options.scaleParameters
    % no action selected
    % show the errors, warnings and notes
    FcnShowMsg(userData);
    return;
end

set(userData.statusLine.handle,'string','Calculate scaling ...');

switch options.rangeOrigin
    case 1 % autoscaling with simulation data
        % check if a netlist available
        bAskForNetlist = 0;
        if ~isfield(userData,'asds')
            % no netlist
            if (options.scaleOutputs || options.scaleStates) &&  options.rangeOrigin == 1
                bAskForNetlist = 1;
            end
        else
            if ~isempty(userData.asds)
                if isempty(userData.asds.netlist) || length(fieldnames(userData.asds.netlist)) == 15
                    % net list without connection data
                    if (options.scaleOutputs || options.scaleStates) &&  options.rangeOrigin == 1
                        bAskForNetlist = 1;
                    end
                end
            end
        end

        if bAskForNetlist
            % create a dialog
            action = questdlg([ ...
                'Currently, there is no netlist available. Do you wish to have one created?' char(10) char(10) ...
                'Note: Output/State scaling based on simulation ranges is possible without netlist. ' ...
                'Creating a netlist is time consuming, but usually improves scaling results.' ...
                ], ...
                'Question');
            pause(0.1);
            switch lower(action)
                case 'yes'
                    bUseNetlist = 1;
                case 'no'
                    bUseNetlist = 0;
                    % bypass without netlist
                    asds.options      = options;
                    asds.netlist      = [];
                    asds.looplist     = [];
                    asds.status       = [];
                case 'cancel'
                    % show the errors, warnings and notes
                    FcnShowMsg(userData);
                    return;
            end
        else
            % no dialog
            if (options.scaleOutputs || options.scaleStates)
                % use the available netlist
                bUseNetlist = 1;
            else
                % bypass without netlist
                bUseNetlist = 0;
            end
        end

        if bUseNetlist
            if isfield(userData,'asds')
                % use the existing netlist for scaling with simulation data
                userData.asds = tl_autoscaling('calculatescaling', ...
                    'useexistingasds',userData.asds, ...
                    'useoptionsstruct',options);
            else
                % create a netlist for scaling with simulation data
                userData.asds = tl_autoscaling('calculatescaling', ...
                    'useoptionsstruct',options);
            end
        else
            % call with empty netlist for scaling with simulation data
            % bypass without netlist
            asds.options      = options;
            asds.netlist      = [];
            asds.looplist     = [];
            asds.status       = [];
            userData.asds = tl_autoscaling('calculatescaling', ...
                'useexistingasds',asds, ...
                'useoptionsstruct',options);
            bClearUserData = 1;
        end

    case 2 % autoscaling with worst-case data
        if isfield(userData,'asds')
            % calculate with existing asds
            userData.asds = tl_autoscaling('calculatescaling', ...
                'useexistingasds',userData.asds, ...
                'useoptionsstruct',options);
        else
            % create asds
            userData.asds = tl_autoscaling('calculatescaling', ...
                'useoptionsstruct',options);
        end
end
[exept,userData] = FcnCatchError(userData,backupASDS);
if exept
    return;
end

% update status line
userData = FcnUpdateStatusLine(userData,0);
% show the errors, warnings and notes
FcnShowMsg(userData);

if bClearUserData
    userData.asds = [];
    userData      = rmfield(userData,'asds');
end

userData.bApplyUiControls = 1;
userData.bApplyData       = 0;
userData.bClose           = 0;

%================================================================================
%% resetscaling
%================================================================================
function userData = FcnResetScaling(userData)

set(userData.statusLine.handle,'string','Reset scaling ...');
[options,backupASDS] = FcnPrepare(userData);
[exept,userData] = FcnCatchError(userData,backupASDS);
if exept
    return;
end

% call API command
if isfield(userData,'asds')
    userData.asds = tl_autoscaling('resetscaling', ...
        'useexistingasds',userData.asds, ...
        'useoptionsstruct',options);
else
    userData.asds = tl_autoscaling('resetscaling', ...
        'useoptionsstruct',options);
end
[exept,userData] = FcnCatchError(userData,backupASDS);
if exept
    return;
end

% update status line
userData = FcnUpdateStatusLine(userData,0);
% show the errors, warnings and notes
FcnShowMsg(userData);

userData.bApplyUiControls = 1;
userData.bApplyData       = 0;
userData.bClose           = 0;

%================================================================================
%% showscaling
%================================================================================
function userData = FcnShowScaling(userData)

set(userData.statusLine.handle,'string','Show scaling ...');
[options,backupASDS] = FcnPrepare(userData);
[exept,userData] = FcnCatchError(userData,backupASDS);
if exept
    return;
end

if isfield(userData,'asds')
    userData.asds = tl_autoscaling('showscaling', ...
        'useexistingasds',userData.asds, ...
        'useoptionsstruct',options);
else
    tl_autoscaling('showscaling', ...
        'useoptionsstruct',options);
    set(userData.statusLine.handle,'string','Ready ...');
end
[exept,userData] = FcnCatchError(userData,backupASDS);
if exept
    return;
end

% update status line
userData = FcnUpdateStatusLine(userData,0);
% show the errors, warnings and notes
FcnShowMsg(userData);

userData.bApplyUiControls = 1;
userData.bApplyData       = 0;
userData.bClose           = 0;


%================================================================================
%% hidescaling
%================================================================================
function userData = FcnHideScaling(userData)

set(userData.statusLine.handle,'string','Hide scaling ...');
[options,backupASDS] = FcnPrepare(userData);
[exept,userData] = FcnCatchError(userData,backupASDS);
if exept
    return;
end

if isfield(userData,'asds')
    if options.TLsystemh == userData.asds.options.TLsystemh
        userData.asds.options = options;
        userData.asds = tl_autoscaling('hidescaling', ...
            'useexistingasds',userData.asds, ...
            'useoptionsstruct',options);
    end
else
    tl_autoscaling('hidescaling', ...
        'useoptionsstruct',options);
end
[exept,userData] = FcnCatchError(userData,backupASDS);
if exept
    return;
end

% update status line
userData = FcnUpdateStatusLine(userData,0);
% show the errors, warnings and notes
FcnShowMsg(userData);

userData.bApplyUiControls = 1;
userData.bApplyData       = 0;
userData.bClose           = 0;


%================================================================================
%% apply
%================================================================================
function userData = FcnApply(userData)

userData.bApplyUiControls = 1;
userData.bApplyData       = 1;
userData.bClose           = 0;

%================================================================================
%% revert
%================================================================================
function userData = FcnRevert(userData)

% synchronize the data after revert
userData = FcnSync(userData);

userData.bApplyUiControls = 1;
userData.bApplyData       = 1;
userData.bClose           = 0;

%================================================================================
%% help
%================================================================================
function userData = FcnHelp(userData)

% refer to TargetLinks online help
tl_online_help('Topic', 'TL_Autoscaling');

userData.bApplyUiControls = 1;
userData.bApplyData       = 1;
userData.bClose           = 0;

%================================================================================
%% cancel
%================================================================================
function userData = FcnCancel(userData)

set(userData.hDlg,'pointer','watch');

% update options
options = FcnGetOptions(userData);
if ds_error_check('Fatals')
    return;
end

if ~isempty(userData)
    if isfield(userData,'asds') && ~isempty(userData.asds)
        % get all blocks below the TL_subsystem
        userData.asds.status.scope = tl_get_subset(userData.asds.options.TLsystemh,userData.asds.netlist,0,0);
        try
            tl_restore_AFS(userData.asds,userData.asds.status.scope);
            scope = [userData.asds.netlist(userData.asds.status.scope).handle];
            for handle = scope
                set_param(handle,'HiliteAncestors','none');
            end
            % set the show flag of all blocks below the TL_subsystem to 0
            FcnSetShowFlag(options,0);
        catch
            userData.asds = [];
            userData = rmfield(userData,'asds');
        end
    else
        % reset hiliting for blocks which are below the TLSubsystem
        scope = tl_get_blocks(options.subsystemh,'TLScalable')';
        for handle = scope
            set_param(handle,'HiliteAncestors','none');
        end
        % set the show flag of all blocks below the TL_subsystem to 0
        FcnSetShowFlag(options,0);
    end
    hModel = userData.hModel;
    set_param(hModel,'CloseFcn','')
end

userData.asds = [];
userData = rmfield(userData,'asds');
clear global HANDLELIST;

userData.bApplyUiControls = 0;
userData.bApplyData       = 0;
userData.bClose           = 1;

set(userData.hDlg,'pointer','arrow');

%================================================================================
%% close
%================================================================================
function userData = FcnClose(userData)

% the same as cancel
userData = FcnCancel(userData);

userData.bApplyUiControls = 1;
userData.bApplyData       = 1;
userData.bClose           = 1;

%================================================================================
%% internal sync
%================================================================================
function userData = FcnSync(userData)

if userData.currentUiControl == 0
    hModel = userData.hModel;
    set_param(hModel,'CloseFcn', ...
        'ds_generic_dlg(''DeleteDialog'',get_param(gcs,''handle''))')
end

% set uicontrols autoscale.DDVars enable off/on
scaleOutputs = userData.uiControl(userData.dataDescription.autoscale.outputs.uiControl).value;
userData.uiControl(userData.dataDescription.autoscale.DDvars.uiControl).bEnabled = scaleOutputs;

% set uicontrols autoscale.wordwidth and autoscale.sign enable off/on
scaleParameters = userData.uiControl(userData.dataDescription.autoscale.parameters.uiControl).value;
userData.uiControl(userData.dataDescription.autoscale.sign.uiControl).bEnabled = scaleParameters;
userData.uiControl(userData.dataDescription.autoscale.wordwidth.uiControl).bEnabled = scaleParameters;

% set uicontrols autoscale.ranges enable off/on
scaleStates = userData.uiControl(userData.dataDescription.autoscale.states.uiControl).value;
createNetlist = scaleOutputs | scaleStates;
userData.uiControl(userData.dataDescription.autoscale.ranges.uiControl).bEnabled = createNetlist;

userData.bApplyUiControls = 1;
userData.bApplyData       = 0;
userData.bClose           = 0;


%================================================================================
%% internal code editor
%================================================================================
function userData = FcnCodeEditor(userData)

% search TargetLink subsytems
hTlsystems = get_tlsubsystems(userData.hModel,1);
if ~isempty(hTlsystems)
    for i=1:length(hTlsystems)
        [codefile,blockstr] = get_codefile(hTlsystems(i));
        if ~isempty(codefile)
            codeedit(which(codefile),blockstr);
        end
    end
else
    ds_error_msg( ...
        'TargetLink subsystem could not be found.', ...
        'Title'        ,'Autoscaling Tool Message', ...
        'ShowDialog'   ,'on', ...
        'MessageType'  ,'note');
end


%================================================================================
%% internal create figure window
%================================================================================
function FcnCreate(hModel,hSelectedSubsystem)

% This dialog can be open only in full-featured mode
if strcmp(tl_get_blockset_mode, 'stand-alone')
    ds_error_msg('The TargetLink Autoscaling Dialog is not available in stand-alone mode.', ...
        'Title', 'Dialog cannot be opened');
    return;
end

dataDescription = FcnGetDataDescription;
% if autoscaling is called from PM with a valid TL subsystem handle, write the
% TL subsystem in the edit field of the dialog.
if ~isempty(hSelectedSubsystem) && ~isequal(hModel,hSelectedSubsystem)
    % get the complete path
    subsystemString = getfullname(hSelectedSubsystem);
    % find all CR's
    crIdx = strfind(subsystemString,char(10));
    % replace CR with spaces
    subsystemString(crIdx) = char(32);
    % insert the corrected subsystem string in data Description
    dataDescription.autoscale.subsystem.defaultValue = subsystemString;
end

commonGeom = ds_get_common_geometry;
strings_and_styles = { ...
    'Select current system', 'pushbutton'
    'Calculate worst-case ranges', 'pushbutton'};
[selectSystemButtonSize, autoscalingButtonSize] = ...
    ds_get_uicontrol_sizes(commonGeom, strings_and_styles);

descWidth = autoscalingButtonSize(1) + 2*selectSystemButtonSize(1) + 16;
figureWidth = descWidth + 10;

% create the dialog window
ds_generic_dlg('Create', ...
    'FigureTag',       'TL_Worst_Case_Autoscaling_Tool', ...
    'DataDescription', dataDescription,...
    'Title',           ['Autoscaling Tool: ' get_param(hModel,'Name')], ...
    'FigureWidth',     figureWidth, ...
    'ModelHandle',     hModel, ...
    'SaveLocation',   {'Model','WCA'}, ...
    'CallBackFcn',     mfilename, ...
    'FrameStructure',  {'AutoscalingScope';{'RangesTab','ScalingTab'}},...
    ...
    'Frame',          'AutoscalingScope', ...
    'Tag',            'AutoscalingScope', ...
    'Style',          'frame', ...
    'DisplayText',    'Autoscaling scope', ...
    ...
    'Tag',            'autoscale.subsystem',...
    'Style',          'edit', ...
    'HeadLine',       'System:', ...
    'UiControlWidth',  descWidth, ...
    'SetPosition',    'll = GetPoint(''autoscale.scopeDepth'',''ul'')+2*rowDelta;', ...
    'LabelStrings',   '',...
    'ToolTipString',  'Simulink system to be scaled.', ...
    ...
    'Tag',            'RefreshNetlist',...
    'Style',          'pushbutton', ...
    'LabelStrings',   'Refresh netlist',...
    'SetPosition',    'll = GetPoint(''SelectCurrent'',''lr'')+2*colDelta;', ...
    'UiControlWidth', selectSystemButtonSize(1) - 20, ...
    'ToolTipString',  'Refresh netlist.', ...
    'Interruptible',  'on',...
    ...
    'Tag',            'SelectCurrent',...
    'Style',          'pushbutton', ...
    'LabelStrings',   'Select current system',...
    'SetPosition',    'll = GetPoint(''autoscale.scopeDepth'',''lr'')+3*colDelta+1*rowDelta;', ...
    'UiControlWidth', selectSystemButtonSize(1), ...
    'ToolTipString',  'Select current active system.', ...
    ...
    'Tag',            'autoscale.scopeDepth',...
    'Style',          'radiobutton', ...
    'LabelStrings',   {'Selected system only','Selected system and below'},...
    'ToolTipString',  sprintf('Selected system only.\nSelected system and below.'), ...
    ...
    'Frame',          'RangesTab',...
    'Tag',            'RangesTab',...
    'Style',          'frame',...
    'TabLabel',       'Ranges', ...
    ...
    'Tag',            'PropagateKnownRanges',...
    'Style',          'pushbutton', ...
    'LabelStrings',   'Propagate known ranges',...
    'SetPosition',    'll = GetPoint(''CalculateWorstCaseRanges'',''ul'')+2*rowDelta;', ...
    'UiControlWidth', autoscalingButtonSize(1), ...
    'ToolTipString',  'Propagate known ranges of supported blocks in the selected scope.', ...
    'Interruptible',  'on',...
    ...
    'Tag',            'autoscale.loopHiliteColor',...
    'Style',          'popupmenu', ...
    'HeadLine',       'Highlight loops', ...
    'LabelStrings',   dataDescription.autoscale.loopHiliteColor.validValues,...
    'SetPosition',    'll = GetPoint(''autoscale.rangesHiliteColor'',''ul'')+5*rowDelta;', ...
    'UiControlWidth', autoscalingButtonSize(1), ...
    'ToolTipString',  'Highlight color of unsolveable loops during range calculation.', ...
    ...
    'Tag',            'CalculateWorstCaseRanges',...
    'Style',          'pushbutton', ...
    'LabelStrings',   'Calculate worst-case ranges',...
    'UiControlWidth', autoscalingButtonSize(1), ...
    'SetPosition',    'll = GetPoint(''ResetRanges'',''ul'')+20*rowDelta;', ...
    'ToolTipString',  'Calculate worst-case ranges of supported blocks in the selected scope.', ...
    'Interruptible',  'on',...
    ...
    'Tag',            'autoscale.rangesHiliteColor', ...
    'Style',          'popupmenu', ...
    'HeadLine',       'Highlight blocks with ranges', ...
    'LabelStrings',   dataDescription.autoscale.rangesHiliteColor.validValues,...
    'SetPosition',    'll = GetPoint(''SetRangesColor'',''ul'')+2*rowDelta;', ...
    'UiControlWidth', autoscalingButtonSize(1), ...
    'ToolTipString',  'Highlight color of blocks with ranges.', ...
    ...
    'Tag',            'SetRangesColor',...
    'Style',          'pushbutton', ...
    'LabelStrings',   'Set color', ...
    'SetPosition',    'll = GetPoint(''ResetRangesColor'',''ul'')+2*rowDelta;', ...
    'UiControlWidth', autoscalingButtonSize(1), ...
    'ToolTipString',  'Update block highlighting.', ...
    'Interruptible',  'on',...
    ...
    'Tag',            'ResetRanges',...
    'Style',          'pushbutton', ...
    'LabelStrings',   'Reset ranges',...
    'SetPosition',    'll = GetPoint(''SaveRangesToFile'',''ul'')+2*rowDelta;', ...
    'UiControlWidth', autoscalingButtonSize(1), ...
    'ToolTipString',  'Initialized range structure.', ...
    'Interruptible',  'on',...
    ...
    'Tag',            'ResetRangesColor',...
    'Style',          'pushbutton', ...
    'LabelStrings',   'Reset color',...
    'SetPosition',    'll = GetPoint(''ShowRanges'',''ul'')+2*rowDelta;', ...
    'UiControlWidth', autoscalingButtonSize(1), ...
    'ToolTipString',  'Reset color of highlighted blocks.', ...
    ...
    'Tag',            'ShowRanges',...
    'Style',          'pushbutton', ...
    'LabelStrings',   'Show ranges',...
    'SetPosition',    'cl = GetPoint(''SaveRangesToFile'',''cr'')+14*colDelta;', ...
    'UiControlWidth', autoscalingButtonSize(1), ...
    'ToolTipString',  'Show ranges in the block attribute format string.', ...
    'Interruptible',  'on',...
    ...
    'Tag',            'SaveRangesToFile',...
    'Style',          'pushbutton', ...
    'LabelStrings',   'Save ranges to file ...',...
    'SetPosition',    'll = GetPoint(''LoadRangesFromFile'',''ul'')+2*rowDelta;', ...
    'UiControlWidth', autoscalingButtonSize(1), ...
    'ToolTipString',  'Save ranges to file.', ...
    ...
    'Tag',            'HideRanges',...
    'Style',          'pushbutton', ...
    'LabelStrings',   'Hide ranges',...
    'SetPosition',    'cl = GetPoint(''LoadRangesFromFile'',''cr'')+14*colDelta;', ...
    'UiControlWidth', autoscalingButtonSize(1), ...
    'ToolTipString',  'Hide shown ranges in the attribute format string.', ...
    ...
    'Tag',            'LoadRangesFromFile',...
    'Style',          'pushbutton', ...
    'LabelStrings',   'Load ranges from file ...',...
    'UiControlWidth', autoscalingButtonSize(1), ...
    'ToolTipString',  'Load ranges from file.', ...
    ...
    'Frame',          'ScalingTab',...
    'Tag',            'ScalingTab', ...
    'Style',          'frame', ...
    'TabLabel',       'Scaling', ...
    ...
    'Tag',            'InheritScaling', ...
    'Style',          'pushbutton', ...
    'LabelStrings',   'Inherit scaling', ...
    'SetPosition',    'll = GetPoint(''StartAutoscaling'',''ul'')+2*rowDelta;', ...
    'UiControlWidth', autoscalingButtonSize(1), ...
    'ToolTipString',  'Inherit scaling of supported blocks in the selected scope.', ...
    'Interruptible',  'on', ...
    ...
    'Tag',            'StartAutoscaling', ...
    'Style',          'pushbutton', ...
    'LabelStrings',   'Start autoscaling', ...
    'SetPosition',    'll = GetPoint(''autoscale.defaultWidth'',''ul'')+2*rowDelta;', ...
    'UiControlWidth', autoscalingButtonSize(1), ...
    'ToolTipString',  'Autoscale supported blocks in the selected scope.', ...
    'Interruptible',  'on',...
    ...
    'Tag',            'autoscale.ranges',...
    'Style',          'radiobutton', ...
    'LabelStrings',   {'Use simulation ranges','Use worst-case ranges'},...
    'SetPosition',    'll = GetPoint(''autoscale.defaultWidth'',''lr'')+14*colDelta;', ...
    'ToolTipString',  'Select which ranges should be used for autoscaling.', ...
    ...
    'Tag',            'autoscale.defaultWidth', ...
    'Style',          'popupmenu', ...
    'HeadLine',       'Default variable width', ...
    'LabelStrings',   dataDescription.autoscale.defaultWidth.validValues, ...
    'SetPosition',    'll = GetPoint(''autoscale.outputs'',''ul'')+2*rowDelta;', ...
    'UiControlWidth', autoscalingButtonSize(1), ...
    'ToolTipString',  'Select width of default datatype.', ...
    ...
    'Tag',            'autoscale.outputs', ...
    'Style',          'checkbox', ...
    'LabelStrings',   'Scale outputs', ...
    'SetPosition',    'll = GetPoint(''autoscale.DDvars'',''ul'')+0.5*rowDelta-3*colDelta;', ...
    'ToolTipString',  'Select if outputs should be scaled.', ...
    ...
    'Tag',            'autoscale.DDvars', ...
    'Style',          'checkbox', ...
    'LabelStrings',   'Scale DataDictionary Variables',...
    'SetPosition',    'll = GetPoint(''autoscale.states'',''ul'')+1.5*rowDelta+3*colDelta;', ...
    'ToolTipString',  'Select if DataDictionary Variables should be scaled.', ...
    ...
    'Tag',            'autoscale.states', ...
    'Style',          'checkbox', ...
    'LabelStrings',   'Scale states',...
    'SetPosition',    'll = GetPoint(''autoscale.parameters'',''ul'')+1.5*rowDelta;', ...
    'ToolTipString',  'Select if states should be scaled.', ...
    ...
    'Tag',            'autoscale.parameters',...
    'Style',          'checkbox', ...
    'LabelStrings',   'Scale parameters',...
    'SetPosition',    'll = GetPoint(''autoscale.sign'',''ul'')+0.5*rowDelta-3*colDelta;', ...
    'ToolTipString',  'Select if parameters should be scaled.', ...
    ...
    'Tag',            'autoscale.sign',...
    'Style',          'checkbox', ...
    'LabelStrings',   'Select datatype sign',...
    'SetPosition',    'll = GetPoint(''autoscale.wordwidth'',''ul'')+0.5*rowDelta;', ...
    'ToolTipString',  'Select if sign of parameter datatype can be changed.', ...
    ...
    'Tag',            'autoscale.wordwidth',...
    'Style',          'checkbox', ...
    'LabelStrings',   'Minimize variable width',...
    'SetPosition',    'll = GetPoint(''ResetScaling'',''ul'')+2*rowDelta+3*colDelta;', ...
    'ToolTipString',  'Select if variable width of parameter should be minimized.', ...
    ...
    'Tag',            'autoscale.scalingHiliteColor',...
    'Style',          'popupmenu', ...
    'HeadLine',       'Highlight scaled blocks', ...
    'LabelStrings',   dataDescription.autoscale.scalingHiliteColor.validValues,...
    'SetPosition',    'll = GetPoint(''SetScalingColor'',''ul'')+2*rowDelta;', ...
    'UiControlWidth', autoscalingButtonSize(1), ...
    'ToolTipString',  'Highlight color of scaled blocks.', ...
    ...
    'Tag',            'SetScalingColor',...
    'Style',          'pushbutton', ...
    'LabelStrings',   'Set color',...
    'SetPosition',    'll = GetPoint(''ResetScalingColor'',''ul'')+2*rowDelta;', ...
    'UiControlWidth', autoscalingButtonSize(1), ...
    'ToolTipString',  'Update highlighted blocks.', ...
    'Interruptible',  'on',...
    ...
    'Tag',            'ResetScalingColor',...
    'Style',          'pushbutton', ...
    'LabelStrings',   'Reset color',...
    'SetPosition',    'll = GetPoint(''ShowScaling'',''ul'')+2*rowDelta;', ...
    'UiControlWidth', autoscalingButtonSize(1), ...
    'ToolTipString',  'Reset Scaling Color', ...
    ...
    'Tag',            'ShowScaling',...
    'Style',          'pushbutton', ...
    'LabelStrings',   'Show scaling',...
    'SetPosition',    'll = GetPoint(''HideScaling'',''ul'')+2*rowDelta;', ...
    'UiControlWidth', autoscalingButtonSize(1), ...
    'ToolTipString',  'Show scaling in the attribute format string.', ...
    'Interruptible',  'on',...
    ...
    'Tag',            'HideScaling',...
    'Style',          'pushbutton', ...
    'LabelStrings',   'Hide scaling',...
    'SetPosition',    'cl = GetPoint(''ResetScaling'',''cr'')+14*colDelta;', ...
    'UiControlWidth', autoscalingButtonSize(1), ...
    'ToolTipString',  'Hide shown scaling in the attribute format string.', ...
    ...
    'Tag',            'ResetScaling',...
    'Style',          'pushbutton', ...
    'LabelStrings',   'Reset scaling',...
    'UiControlWidth', autoscalingButtonSize(1), ...
    'ToolTipString',  'Initialize scaling structure.', ...
    'Interruptible',  'on',...
    ...
    'MenuButton',         'DDMan', ...
    'MenuButtonCallBack', 'dsddman;', ...
    'MenuButton',         'CodeEdit', ...
    'MenuButton',         'PropMan', ...
    'MenuButtonCallBack', 'tl_propman(bdroot(gcbh));', ...
    'MenuButton',         'Help', ...
    ...
    'ButtonName',      'Apply', ...
    'ButtonName',      'Revert', ...
    'ButtonName',      'Help', ...
    'ButtonName',      'Cancel', ...
    'ButtonName',      'Close', ...
    ...
    'DefaultButton',   'Cancel', ...
    'StatusLine',      'Ready');


%-----------------------------------------------------------
%% internal get data description
%-----------------------------------------------------------
function dataDescription = FcnGetDataDescription

% get basic data types
dataTypeWidth = {'8 bit', '16 bit', '32 bit'};

% get default color
highlightColorMap = {'none'; 'Black'; 'White'; 'Red'; 'Green'; 'Blue'; 'Cyan';
    'Magenta'; 'Yellow'; 'Gray'; 'Light Blue'; 'Orange';
    'Dark Green'};

dataDescription.callBackActions = {
    'SelectCurrent'
    'RefreshNetlist'
    'PropagateKnownRanges'
    'CalculateWorstCaseRanges'
    'SetRangesColor'
    'ResetRanges'
    'ResetRangesColor'
    'SaveRangesToFile'
    'ShowRanges'
    'LoadRangesFromFile'
    'HideRanges'
    'InheritScaling'
    'StartAutoscaling'
    'SetScalingColor'
    'ResetScalingColor'
    'ResetScaling'
    'ShowScaling'
    'ApplyScaling'
    'HideScaling'
    'Apply'
    'Revert'
    'Help'
    'Cancel'
    'Close'
    'getdatadescription'
    'Sync'
    'codeedit'
    };

% list of all property names
dataDescription.propertyNames = {
    'revisionNumber';
    'autoscale.verbose';
    'autoscale.subsystem';
    'autoscale.scopeDepth';
    'autoscale.defaultWidth';
    'autoscale.outputs';
    'autoscale.states';
    'autoscale.DDvars';
    'autoscale.parameters';
    'autoscale.sign';
    'autoscale.wordwidth';
    'autoscale.scalingHiliteColor';
    'autoscale.rangesHiliteColor';
    'autoscale.loopHiliteColor';
    'autoscale.ranges'};

% revisionNumber
dataDescription.revisionNumber.dataType     = 'integer';
dataDescription.revisionNumber.validValues  = [];
dataDescription.revisionNumber.defaultValue = 2;
dataDescription.revisionNumber.attributes   = {'read-only','hidden'};

% autoscale.verbose
dataDescription.autoscale.verbose.dataType     = 'integer';
dataDescription.autoscale.verbose.validValues  = [];
dataDescription.autoscale.verbose.defaultValue = 1;
dataDescription.autoscale.verbose.attributes   = {'hidden'};

% autoscale.subsystem
dataDescription.autoscale.subsystem.dataType     = 'string';
dataDescription.autoscale.subsystem.validValues  = '';
dataDescription.autoscale.subsystem.defaultValue = '';
dataDescription.autoscale.subsystem.attributes   = {'never-save'};

% autoscale.scopeDepth
dataDescription.autoscale.scopeDepth.dataType     = 'integer';
dataDescription.autoscale.scopeDepth.validValues  = [];
dataDescription.autoscale.scopeDepth.defaultValue = 1;
dataDescription.autoscale.scopeDepth.attributes   = {};

% autoscale.outputs
dataDescription.autoscale.outputs.dataType     = 'integer';
dataDescription.autoscale.outputs.validValues  = [];
dataDescription.autoscale.outputs.defaultValue = 1;
dataDescription.autoscale.outputs.attributes   = {};

% dataTypeWidth
dataDescription.autoscale.defaultWidth.dataType     = 'string';
dataDescription.autoscale.defaultWidth.validValues  = dataTypeWidth;
dataDescription.autoscale.defaultWidth.defaultValue = dataTypeWidth{2};
dataDescription.autoscale.defaultWidth.attributes   = {};

% autoscale.DDvars
dataDescription.autoscale.DDvars.dataType     = 'integer';
dataDescription.autoscale.DDvars.validValues  = [];
dataDescription.autoscale.DDvars.defaultValue = 0;
dataDescription.autoscale.DDvars.attributes   = {};

% autoscale.states
dataDescription.autoscale.states.dataType     = 'integer';
dataDescription.autoscale.states.validValues  = [];
dataDescription.autoscale.states.defaultValue = 1;
dataDescription.autoscale.states.attributes   = {};

% autoscale.parameters
dataDescription.autoscale.parameters.dataType     = 'integer';
dataDescription.autoscale.parameters.validValues  = [];
dataDescription.autoscale.parameters.defaultValue = 0;
dataDescription.autoscale.parameters.attributes   = {};

% autoscale.sign
dataDescription.autoscale.sign.dataType     = 'integer';
dataDescription.autoscale.sign.validValues  = [];
dataDescription.autoscale.sign.defaultValue = 0;
dataDescription.autoscale.sign.attributes   = {};

% autoscale.wordwidth
dataDescription.autoscale.wordwidth.dataType     = 'integer';
dataDescription.autoscale.wordwidth.validValues  = [];
dataDescription.autoscale.wordwidth.defaultValue = 0;
dataDescription.autoscale.wordwidth.attributes   = {};

% autoscale.scalingHiliteColor
dataDescription.autoscale.scalingHiliteColor.dataType     = 'string';
dataDescription.autoscale.scalingHiliteColor.validValues  = highlightColorMap;
dataDescription.autoscale.scalingHiliteColor.defaultValue = highlightColorMap{5};
dataDescription.autoscale.scalingHiliteColor.attributes   = {};

% autoscale.rangesHiliteColor
dataDescription.autoscale.rangesHiliteColor.dataType     = 'string';
dataDescription.autoscale.rangesHiliteColor.validValues  = highlightColorMap;
dataDescription.autoscale.rangesHiliteColor.defaultValue = highlightColorMap{6};
dataDescription.autoscale.rangesHiliteColor.attributes   = {};

% autoscale.loopHiliteColor
dataDescription.autoscale.loopHiliteColor.dataType     = 'string';
dataDescription.autoscale.loopHiliteColor.validValues  = highlightColorMap;
dataDescription.autoscale.loopHiliteColor.defaultValue = highlightColorMap{4};
dataDescription.autoscale.loopHiliteColor.attributes   = {};

% autoscale.ranges
dataDescription.autoscale.ranges.dataType     = 'integer';
dataDescription.autoscale.ranges.validValues  = [];
dataDescription.autoscale.ranges.defaultValue = 2;
dataDescription.autoscale.ranges.attributes   = {};


%------------------------------------------------------------------------------
%% internal get options
%------------------------------------------------------------------------------
function options = FcnGetOptions(userData)

options = struct( ...
    'gui',                1, ...  % gui : 0 = commandline 1 = gui
    'rangeOrigin',        1, ...  % 1 = sim 2 = calculated
    'TLsystemh',          [], ... %
    'subsystemh',         [], ... %
    'workmode',           1, ...  % 1 = subsystem 2 = subsystem ans below
    'scope',              [], ... % all blocks which are in scope
    'color',              struct('loopAvailable','','rangeAvailable','','scalingAvailable',''), ...
    'defaultWidth',       [], ... %
    'scaleOutputs',       [], ... %
    'scaleDDVars',        [], ... %
    'scaleStates',        [], ... %
    'scaleParameters',    [], ... %
    'selectDatatypeSign', [], ... %
    'minParaWidth',       []);    %

% userData.uiControl(2).tag = 'autoscale.subsystem'
if ~isempty(userData.uiControl(2).value)
    msgData = ds_error_get('CurrentState');
    [dummyPath,tlPath] = get_tlsubsystempath(userData.uiControl(2).value);
    % tlPath is empty, if TL subsystem or block outside TL system is selected
    % dummyPath contains path between selected block and TL system
    if ~isempty(tlPath)
        tlSubInfo = tl_get_subsystem_info(tlPath);
    else
        tlSubInfo = tl_get_subsystem_info(dummyPath);
    end
    ds_error_merge(msgData);
else
    ds_error_msg( ...
        'No valid TargetLink subsystem selected.', ...
        'Title'        ,'Autoscaling Tool Message', ...
        'ShowDialog'   ,'off', ...
        'MessageType'  ,'fatal', ...
        'MessageNumber', 03464);
    return;
end

% get the tlsubsystem handle
if  ~isempty(tlSubInfo.tlSubsystemPath) && ~isempty(userData.uiControl(2).value)
    options.TLsystemh  = get_param(tlSubInfo.tlSubsystemPath,'Handle');
    if length(userData.uiControl(2).value) < length(tlSubInfo.milSubsystemPath)
        % select the Mil subsystem if path shorter than Mil subsystem path
        options.subsystemh = get_param(tlSubInfo.milSubsystemPath,'Handle');
    else
        options.subsystemh = get_param(userData.uiControl(2).value,'Handle');
    end
else
    ds_error_msg( ...
        'No valid TargetLink subsystem selected.', ...
        'Title'        ,'Autoscaling Tool Message', ...
        'ShowDialog'   ,'off', ...
        'MessageType'  ,'fatal', ...
        'MessageNumber', 03464);
    return;
end

% get the scope depth
% userData.uiControl(3).tag = 'autoscale.scopeDepth'
options.workmode   = userData.uiControl(3).value;

% ranges tab
% userData.uiControl(5).tag = 'autoscale.loopHiliteColor'
switch userData.uiControl(5).value
    case 'Black'
        options.color.loopAvailable = 'black';
    case 'White'
        options.color.loopAvailable = 'white';
    case 'Red'
        options.color.loopAvailable = 'red';
    case 'Green'
        options.color.loopAvailable = 'green';
    case 'Blue'
        options.color.loopAvailable = 'blue';
    case 'Cyan'
        options.color.loopAvailable = 'cyan';
    case 'Magenta'
        options.color.loopAvailable = 'magenta';
    case 'Yellow'
        options.color.loopAvailable = 'yellow';
    case 'Gray'
        options.color.loopAvailable = 'gray';
    case 'Light Blue'
        options.color.loopAvailable = 'lightblue';
    case 'Orange'
        options.color.loopAvailable = 'orange';
    case 'Dark Green'
        options.color.loopAvailable = 'darkgreen';
    otherwise
        options.color.loopAvailable = 'none';
end

% userData.uiControl(6).tag = 'autoscale.loopHiliteColor'
switch userData.uiControl(6).value
    case 'Black'
        options.color.rangeAvailable = 'black';
    case 'White'
        options.color.rangeAvailable = 'white';
    case 'Red'
        options.color.rangeAvailable = 'red';
    case 'Green'
        options.color.rangeAvailable = 'green';
    case 'Blue'
        options.color.rangeAvailable = 'blue';
    case 'Cyan'
        options.color.rangeAvailable = 'cyan';
    case 'Magenta'
        options.color.rangeAvailable = 'magenta';
    case 'Yellow'
        options.color.rangeAvailable = 'yellow';
    case 'Gray'
        options.color.rangeAvailable = 'gray';
    case 'Light Blue'
        options.color.rangeAvailable = 'lightblue';
    case 'Orange'
        options.color.rangeAvailable = 'orange';
    case 'Dark Green'
        options.color.rangeAvailable = 'darkgreen';
    otherwise
        options.color.rangeAvailable = 'none';
end

% scaling tab
% userData.uiControl(9).tag = 'autoscale.defaultWidth'
switch userData.uiControl(9).value
    case '8 bit'
        options.defaultType = 'Int8';
    case '16 bit'
        options.defaultType = 'Int16';
    case '32 bit'
        options.defaultType = 'Int32';
end

options.rangeOrigin            = userData.uiControl(8).value;
options.scaleOutputs           = userData.uiControl(10).value;
options.scaleDDVars            = userData.uiControl(11).value;
options.scaleStates            = userData.uiControl(12).value;
options.scaleParameters        = userData.uiControl(13).value;
options.selectDatatypeSign     = userData.uiControl(14).value;
options.minParaWidth           = userData.uiControl(15).value;

switch userData.uiControl(16).value
    case 'Black'
        options.color.scalingAvailable = 'black';
    case 'White'
        options.color.scalingAvailable = 'white';
    case 'Red'
        options.color.scalingAvailable = 'red';
    case 'Green'
        options.color.scalingAvailable = 'green';
    case 'Blue'
        options.color.scalingAvailable = 'blue';
    case 'Cyan'
        options.color.scalingAvailable = 'cyan';
    case 'Magenta'
        options.color.scalingAvailable = 'magenta';
    case 'Yellow'
        options.color.scalingAvailable = 'yellow';
    case 'Gray'
        options.color.scalingAvailable = 'gray';
    case 'Light Blue'
        options.color.scalingAvailable = 'lightblue';
    case 'Orange'
        options.color.scalingAvailable = 'orange';
    case 'Dark Green'
        options.color.scalingAvailable = 'darkgreen';
    otherwise
        options.color.scalingAvailable = 'none';
end

%------------------------------------------------------------------------------
%% internal show messages
%------------------------------------------------------------------------------
function FcnShowMsg(userData)

if ds_error_check('Fatals') ...
        || ds_error_check('Errors') ...
        || ds_error_check('Warnings') ...
        || ds_error_check('Notes')
    if tl_msgdlg('find')
        tl_msgdlg('update');
    else
        tl_msgdlg('show');
    end
    ds_error_clear;
else
    tl_msgdlg('Close');
end
set(userData.hDlg,'pointer','arrow');

%------------------------------------------------------------------------------
%% internal update hiliting
%------------------------------------------------------------------------------
function userData = FcnUpdateHiliting(userData)

% get the blocks to highlight
userData.asds = tl_get_blocks2hilite(userData.asds);
if ds_error_check('Fatals')
    return;
end

tl_hilite_blocks(userData.asds);

%------------------------------------------------------------------------------
%% internal update status line
%------------------------------------------------------------------------------
function userData = FcnUpdateStatusLine(userData, bIsMainAction)

if isfield(userData,'asds')
    % initialize toScale
    toScale = [];
    % blocks in scope
    scope = userData.asds.status.scope;
    numInScope    = length(scope);
    % get all blocks with ranges
    numWithRange = length(userData.asds.status.range);
    % get all blocks with autoscaling on and no scaling
    for i = scope
        bToScale = any(find([userData.asds.netlist(i).autoscalingmode]));
        if bToScale
            toScale = [toScale i]; %#ok<AGROW>
        end
    end
    isScaled    = intersect(toScale,userData.asds.status.scaling);
    numToScale  = length(toScale);
    numScaled   = length(isScaled);

    msg = sprintf('%d blocks in scope, %d with range, %d of %d scaled ',numInScope,numWithRange,numScaled,numToScale);
    set(userData.statusLine.handle,'string',msg);
    if isempty(toScale) && bIsMainAction
        ds_error_msg( ...
            'Autoscaling method of ALL blocks in current scope is set to ''No autoscaling''.', ...
            'Title'        ,'Autoscaling Tool Message', ...
            'ShowDialog'   ,'off', ...
            'MessageType'  ,'warning', ...
            'MessageNumber', 03458);
    end
else
    set(userData.statusLine.handle,'string','Ready ...');
end

%------------------------------------------------------------------------------
%% internal update status
%------------------------------------------------------------------------------
function userData = FcnUpdateStatus(userData)

% get the selected subset
subset = userData.asds.status.scope;

% update the range status
blocksWithRange = tl_get_blocks_with_status('range',[2 3 4],userData.asds,subset);
OutportIdx = find(ismember({userData.asds.netlist(blocksWithRange.inport).blockType},'Outport'));
userData.asds.status.range = [blocksWithRange.outport blocksWithRange.inport(OutportIdx)]; %#ok<FNDSB>

% update the scaling status
blocksWithScaling = tl_get_blocks_with_status('scaling',[2 3 6],userData.asds,subset);
userData.asds.status.scaling = blocksWithScaling.outport;

%------------------------------------------------------------------------------
%% internal update status, afs, hiliting and status line
%------------------------------------------------------------------------------
function userData = FcnUpdate(userData, bIsMainAction)

% update status
userData = FcnUpdateStatus(userData);
if ds_error_check('Fatals')
    return;
end

if ~isempty(userData.asds.status.show.range)
    % update the ranges in AFS
    set(userData.statusLine.handle,'string','Update the shown data ... ');
    tl_print_AFS('range',userData.asds);
    if ds_error_check('Fatals')
        return;
    end
end

if ~isempty(userData.asds.status.show.scaling)
    % update the ranges in AFS
    set(userData.statusLine.handle,'string','Update the shown data ... ');
    tl_print_AFS('scaling',userData.asds);
    if ds_error_check('Fatals')
        return;
    end
end

if ~isempty(userData.asds.status.hilite)
    % update hiliting
    set(userData.statusLine.handle,'string','Update the highlighted blocks ... ');
    userData = FcnUpdateHiliting(userData);
    if ds_error_check('Fatals')
        return;
    end
end

userData.asds.status.badloops = [];

% update status line
userData = FcnUpdateStatusLine(userData, bIsMainAction);

%------------------------------------------------------------------------------
%% internal reset ASDS
%------------------------------------------------------------------------------
function userData = FcnResetASDS(userData,backupASDS)

try
    % show messages
    FcnShowMsg(userData);
    % restore asds
    userData.asds = backupASDS;
    userData = FcnUpdate(userData,1);
    set(userData.hDlg,'pointer','arrow');
catch
    userData.asds = [];
    userData = rmfield(userData,'asds');
    set(userData.statusLine.handle,'string','Ready');
    FcnShowMsg(userData);
    set(userData.hDlg,'pointer','arrow');
end

%------------------------------------------------------------------------------
%% internal reset show flag
%------------------------------------------------------------------------------
function FcnSetShowFlag(options,value)

tlBlocks = tl_manage_blockset('GetTLBlocktypes');
% get all blocks below the TL simframe
if options.workmode == 1
    % subsystem only
    allBlocks = find_system(options.subsystemh,'LookUnderMasks','all','FollowLinks', 'on','SearchDepth',1);
end

if options.workmode == 2
    % subsystem and below
    allBlocks = find_system(options.subsystemh,'LookUnderMasks','all','FollowLinks', 'on');
end

for k = 1:length(allBlocks)
    if ishandle(allBlocks(k))
        maskType = get_param(allBlocks(k),'maskType');
        switch maskType
            case tlBlocks
                parent = get_param(allBlocks(k),'parent');
                linkStatus = get_param(parent,'LinkStatus');
                switch linkStatus
                    case {'none' 'inactive'}
                        tldata = get_tlcg_data(allBlocks(k));
                        if isfield(tldata,'output')
                            for n = 1:length(tldata.output)
                                if isfield(tldata.output(n),'show')
                                    if tldata.output(n).show ~= value
                                        tldata.output(n).show = value;
                                        set_tlcg_data(allBlocks(k),tldata);
                                    end
                                end
                            end
                        end
                end
        end
    end
end

%------------------------------------------------------------------------------
%% catch error
%------------------------------------------------------------------------------
function [exept,userData] = FcnCatchError(userData,backupASDS)

if ds_error_check('Fatals')
    if isfield(userData,'asds')
        if ~isempty(backupASDS)
            % FcnResetASDS calls FcnShowMsg
            userData = FcnResetASDS(userData,backupASDS);
        else
            userData = rmfield(userData,'asds');
            % show the errors, warnings and notes
            FcnShowMsg(userData);
        end
    else
        % show the errors, warnings and notes
        FcnShowMsg(userData);
    end
    set(userData.statusLine.handle,'string','Error');
    exept = 1;
else
    exept = 0;
end

%------------------------------------------------------------------------------
%% prepare action
%------------------------------------------------------------------------------
function [options,backupASDS] = FcnPrepare(userData)

set(userData.hDlg,'pointer','watch');

if isfield(userData,'asds')
    % create a backup of asds
    backupASDS = userData.asds;
else
    backupASDS = [];
end

% clear pending error messages
ds_error_none;
% update options
options = FcnGetOptions(userData);
if ds_error_check('Fatals')
    return;
end
